package com.net;

import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeoutException;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Process;

import com.bean.UpdateBean;
import com.constant.Constant;
import com.data.BaseData;
import com.data.CDJobData;
import com.data.ExamineData;
import com.data.GradeViewStateData;
import com.data.JobData;
import com.data.LoginEduSystemData;
import com.data.LoginLibraryData;
import com.data.LoginLibraryData;
import com.data.MoreJobData;
import com.data.RenewBookData;
import com.data.ScheduleData;
import com.data.ScoreQueryData;
import com.data.SearchLibraryData;
import com.data.TeacherScheduleData;
import com.data.TeachingListData;
/**
 * 加载数据接口类
 * 
 * 该类的实现为：
 * 使用两个静态内部类，对消息进行调度，主要是为了节约handler资源，
 * MESSAGE_OK:表示数据请求成功
 * MESSAGE_ERROR:表示数据请求失败
 * sThreadPool:线程池提交接口
 * sHandler：handler数据处理接口
 * @author mjh
 *
 */

/*线程池ThreadPoolExecutor的构造方法为：ThreadPoolExecutor(int corePoolSize, int maximumPoolSize,

long keepAliveTime, TimeUnit unit,
 
BlockingQueue<Runnable> workQueue,
 
RejectedExecutionHandler handler)

corePoolSize： 线程池维护线程的最少数量
 
maximumPoolSize：线程池维护线程的最大数量
 
keepAliveTime： 线程池维护线程所允许的空闲时间
 
unit： 线程池维护线程所允许的空闲时间的单位
 
workQueue： 线程池所使用的缓冲队列
 
handler： 线程池对拒绝任务的处理策略


 * 为了便于跨大量上下文使用，此类提供了很多可调整的参数和扩展挂钩。
 * 但是，强烈建议程序员使用较为方便的 Executors 
 * 工厂方法 Executors.newCachedThreadPool()（无界线程池，可以进行自动线程回收）
 * 工厂将最大池的大小设置为Integer.MAX_VALUE，核心池的大小设置为0，超时设置为一分钟。
 * 这样创建了无限扩大的线程池，会在需求量减少的情况下减少线程数量。
 * Executors.newFixedThreadPool(int)（固定大小线程池）
 * 工厂为请求的池设置了核心池的大小和最大池的大小，而且池永远不会超时
 * 和 Executors.newSingleThreadExecutor()（单个后台线程池）
 * 它们均为大多数使用场景预定义了设置。
 * */
public final class LoadData
{
	private final static int MESSAGE_OK = 0x1;
	private final static int MESSAGE_ERROR = 0x2;
	private static ThreadPoolExecutor sThreadPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(3);
	private final static IntervalHandler sHandler = new IntervalHandler();//对消息进行处理
	
	public static void clear()
	{
		sThreadPool.shutdown();//关闭已经请求的线程，如果该线程已经结束，则不会有任何影响，
		//当前没有响应的线程也会关闭，如果不想关闭还没有响应的线程，可以使用awaitTermination()
	}
	
	public static void shutdownNow()
	{
		sThreadPool.shutdownNow();//停止当前活动的任务
	}
	
	//装载数据（ 请求的名字 ,网络上请求得到的数据，用户返回请求数据）
	public static void loadData(final String control_name, final RequestParameter parameter,
			final RequestListener listener)
	{
		
		sThreadPool.submit(new Runnable()
		{
			
			public void run()
			{
				// 设置为后台线程，当主线程退出时，所有的后台线程都会退出
				Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
				//设置线程优先级为后台，这样当多个线程并发后很多无关紧要的线程分配的CPU时间将会减少，有利于主线程的处理，
				
				// 保存请求关键字信息
				Bundle bundle = new Bundle();
				bundle.putString("control_name", control_name);
				
				BaseData data = loadData(control_name);
				//根据请求的名字不同，得到不同的数据
				//BaseData是一个抽象类，其他所有的数据类都继承了BaseData。
				Message msg = null;
				
				try
				{
					if(data == null)
					{
						// 请求关键字错误
						 msg = Message.obtain(sHandler, MESSAGE_ERROR, new DataBean(null, listener, 
								 new ClientError(ClientError.ERROR_INTERVAL, "错误消息：请求关键字错误")));
						 data = null;
					}
					else
					{
						// 解析数据
						data.startParse(parameter);
						msg = Message.obtain(sHandler, MESSAGE_OK, new DataBean(data, listener, null));
					}
					
				} 
				catch (SocketTimeoutException e)
				{
					e.printStackTrace();
					msg = Message.obtain(sHandler, MESSAGE_ERROR, new DataBean(null, listener, 
							new ClientError(ClientError.ERROR_TIMEOUT, "错误消息：" + e.getMessage()) ));
					data = null;
				}
				catch(TimeoutException e)
				{
					e.printStackTrace();
					msg = Message.obtain(sHandler, MESSAGE_ERROR, new DataBean(null, listener, 
							new ClientError(ClientError.ERROR_TIMEOUT, "错误消息：" + e.getMessage()) ));
					data = null;
				}
				catch(UnknownHostException e) 
				{ 
					// extends IOException
					e.printStackTrace();
					msg = Message.obtain(sHandler, MESSAGE_ERROR, new DataBean(null, listener, 
							new ClientError(ClientError.ERROR_NETWORK, "错误消息：" + e.getMessage()) ));
					data = null;
					
				}
				catch(ClientException e)
				{
					e.printStackTrace();
					msg = Message.obtain(sHandler, MESSAGE_ERROR, new DataBean(null, listener, 
							new ClientError(e.getErrorCode(), "错误消息：" + e.getMessage()) ));
					data = null;
				}
				catch (Exception e)
				{
					
					e.printStackTrace();
					msg = Message.obtain(sHandler, MESSAGE_ERROR, new DataBean(null, listener, 
							new ClientError(ClientError.ERROR_PRASE_HTML, "错误消息：" + e.getMessage()) ));
					data = null;
					
				}
				finally
				{
					msg.setData(bundle);
					msg.sendToTarget();
				}
				
			} // run
		});
		
	} // loadData
	
	
	private static BaseData loadData(final String control_name)
	{
		BaseData data = null;
		if(control_name.equals(Constant.SEARCH_LIBRARY_DATA))
		{
			data = new SearchLibraryData();
		}
		else if(control_name.equals(Constant.LOGIN_LIBRARY_DATA))
		{
			data = new LoginLibraryData();
		}
		else if(control_name.equals(Constant.JOB_DATA))
		{
			data = new JobData();
		}
		else if(control_name.equals(Constant.MORE_JOB_DATA))
		{
			data = new MoreJobData();
		}
		else if(control_name.equals(Constant.LOGIN_EDU_SYSTEM_DATA))
		{
			data = new LoginEduSystemData();
		}
		else if(control_name.equals(Constant.SCHEDULE_DATA))
		{
			data = new ScheduleData();
		}
		else if(control_name.equals(Constant.EXAMINE_DATA))
		{
			data = new ExamineData();
		}
		else if(control_name.equals(Constant.GRADE_VIEW_STATE_DATA))
		{
			data = new GradeViewStateData();
		}
		else if(control_name.equals(Constant.SCORE_QUERY_DATA))
		{
			data = new ScoreQueryData();
		}
		else if(control_name.equals(Constant.TEACHER_SCHEDULE_DATA))
		{
			data = new TeacherScheduleData();
		}
		else if(control_name.equals(Constant.TEACHING_LIST_DATA))
		{
			data = new TeachingListData();
		}
		else if(control_name.equals(Constant.CD_JOB_DATA))
		{
			data = new CDJobData();
		}
		else if(control_name.equals(Constant.RENEW_BOOK_DATA))
		{
			data = new RenewBookData();
		}
		else if(control_name.equals(Constant.TEST))
		{
			data = new LoginLibraryData();
		}
		else 
		{
			return null;
		}
		
		return data;
		
	} // loadDta
	
	// -------------------------该模块用于加载服务器的反馈信息和统计信息-----------------------------------
	
	public static void loadData(final int control_code, final RequestParameter parameter, final RequestListener listener)
	{
		sThreadPool.submit(new Runnable()
		{
			
			public void run()
			{
				// TODO:一下为统计用户信息，在发布时添加
				
				/*// 设置为后台线程，当主线程退出时，所有的后台线程都会退出
				Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
				Message msg = null;
				
				try
				{
					switch(control_code)
					{
					case Constant.FEEDBACK:
						boolean bSuccess = XiaoYuan.phoneResponse(parameter.getValue("imei"), parameter.getValue("content"));
						if(bSuccess == true)
						{
							msg = Message.obtain(sHandler, MESSAGE_OK, new DataBean("true", listener, null));
						}
						else
						{
							msg = Message.obtain(sHandler, MESSAGE_OK, new DataBean("false", listener, null));
						}
						break;
					case Constant.CHECK_UPDATE:
						UpdateBean update = XiaoYuan.getUpdateInfo();
						msg = Message.obtain(sHandler, MESSAGE_OK, new DataBean(update, listener, null));
						break;
					case Constant.MODULE:
						XiaoYuan.sendStatistics(parameter.getValue("imei"),
								parameter.getValue("channel"), parameter.getValue("per_count"));
						break;
					}
					
					msg.sendToTarget();
				}
				catch (Exception e) 
				{
					msg = Message.obtain(sHandler, MESSAGE_ERROR, 
							new DataBean(null, listener, new ClientError(0, "错误消息：" + e.getMessage())));
					msg.sendToTarget();
				}*/
				
			
			} // run
		});
	} // loadData
	
	
//	// 设置为后台线程，当主线程退出时，所有的后台线程都会退出
//	Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//	Message msg = null;
//	
//	try
//	{
//		switch(control_code)
//		{
//		case Constant.FEEDBACK:
//			boolean bSuccess = XiaoYuan.phoneResponse(parameter.getValue("imei"), parameter.getValue("content"));
//			if(bSuccess == true)
//			{
//				msg = Message.obtain(sHandler, MESSAGE_OK, new DataBean("true", listener, null));
//			}
//			else
//			{
//				msg = Message.obtain(sHandler, MESSAGE_OK, new DataBean("false", listener, null));
//			}
//			break;
//		case Constant.CHECK_UPDATE:
//			UpdateBean update = XiaoYuan.getUpdateInfo();
//			msg = Message.obtain(sHandler, MESSAGE_OK, new DataBean(update, listener, null));
//			break;
//		case Constant.MODULE:
//			XiaoYuan.sendStatistics(parameter.getValue("imei"),
//					parameter.getValue("channel"), parameter.getValue("per_count"));
//			break;
//		}
//		
//		msg.sendToTarget();
//	}
//	catch (Exception e) 
//	{
//		msg = Message.obtain(sHandler, MESSAGE_ERROR, 
//				new DataBean(null, listener, new ClientError(0, "错误消息：" + e.getMessage())));
//		msg.sendToTarget();
//	}
//	
//} // run
	
	
//	private static BaseData loadObject(final int control_code) {
//		
//		BaseData data = null;
//		
//		switch (control_code) {
//		case Constant.FEEDBACK_DATA:
//			data = new FeedbackData();
//			break;
//		case Constant.START_DATA:
//			data = new StartData();
//			break;
//		case Constant.MODULE_DATA:
//			data = new ModuleData();
//			break;
//		case Constant.MESSAGE_DATA:
//			data = new MsgData();
//			break;
//		}
//		
//		return data;
//	}


	/*Handler 消息处理类
	 * （1）将Message或者Runable应用的post()或者sendMessage()方法发送到MessageQueue中，在发送时可以指定
	 * 延迟时间、发送时间、携带的Bundle数据，当MessageQueue循环到该Message类时，调用相应的Handler
	 * 对象的handlerMessage()方法进行处理。
	 * (2)在子线程中与主线程进行通信。
	 * */
	/*Message消息类
	 * 每个消息类都可以通过Message.obtain()或者Handler.obtainMessage()方法获得
	 * 一个消息类有五个属性
	 * arg1     int    存放整型数据
	 * arg2     int    存放整型数据
	 * obj      Obeject 存放发送给接收器的Object类型的任意对象
	 * replyTo  Message  指定此Message发送到何处的可选Mesage对象
	 * what     int     指定自定义的消息代码，这样接受者就知道这个是我要的消息
	 * Message类可以携带int型数据，如果要其他数据，将数据存入Bundle对象中，通过setData()方法添加到Message类中。
	 * */
	/*Handler类和Message的使用
	 * Message m=handler.obtainMessage();//新建一个消息类
	 * m.arg1=1;//传递一个数据为1
	 * Bundle bundle=new Bundle();//新建一个
	 * m.what=0x11;
	 * bundle.putString("消息名称",String);
	 * m.setData(bundle);
	 * handler.sendMessage(m); 
	 * */
	private final static class IntervalHandler extends Handler
	{
		@Override
		public void handleMessage(Message msg)
		{/*处理消息的方法*/
			//super.handleMessage(msg);
			
			DataBean bean = (DataBean) msg.obj;
			if(bean == null || bean.listener == null)
				return;
			
			switch(msg.what)
			{
			case MESSAGE_OK://如果消息代码是1
				bean.listener.onComplete(bean.obj);
				break;
			case MESSAGE_ERROR://如果消息代码是2
				bean.listener.onError(bean.data);
				break;
			}
		} // handleMessage
		
	} // IntervalHandler
	
	
	private final static class DataBean//数据的详细信息
	{
		public Object obj;
		public RequestListener listener;//请求监听器接口
		public ClientError data;//错误信息，有网络连接错误信息，解析html错误等。
		
		public DataBean(Object obj, RequestListener listener, ClientError data)
		{
			super();
			this.obj = obj;
			this.listener = listener;
			this.data = data;
		}
	}
	
}